<h2>Why is this an issue?</h2>
<p>In TypeScript, a type alias is a way to give a name to a specific type. It allows you to create a new name for an existing type, making your code
more expressive and readable. This is especially useful when you are working with complex or lengthy types that you use frequently.</p>
<p>Type aliases should be preferred over complex types like unions or intersections for several reasons:</p>
<ul>
  <li> Type aliases can make your code more readable and maintainable by giving meaningful names to complex types. When you use a type alias, it
  becomes clear what the type represents, making it easier for other developers (including your future self) to understand the code. </li>
  <li> Type aliases promote code reusability. When you define a type alias for a complex type, you can use that alias in multiple places throughout
  your codebase, reducing duplication and promoting consistency. </li>
  <li> Type aliases allow you to abstract away the underlying complexity of types. This promotes encapsulation by hiding implementation details behind
  a well-named alias, allowing you to change the underlying type in the future without affecting the code that uses the alias. </li>
  <li> If you need to modify a complex type, using a type alias means you only need to change the type definition in one place. This change will
  automatically apply to all usages of the alias. </li>
  <li> Type aliases communicate the intent of the type, making it easier for other developers to understand what the type represents. Complex unions
  and intersections, on the other hand, might require additional comments or documentation to explain their purpose. </li>
  <li> Using type aliases can help you avoid excessive nesting of complex types. Nested unions and intersections can quickly become hard to read and
  maintain, and type aliases can simplify the type definitions. </li>
</ul>
<p>This rule enforces the rule of three for code refactoring and reports unions and intersections with three or more constituents appearing at least
three times in the codebase.</p>
<pre data-diff-id="1" data-diff-type="noncompliant">
function foo(x: string | null | number) { // Noncompliant: The union has three constituents and is duplicated three times in the code
  /* ... */
}

let bar: string | null | number = /* ... */;

function baz(): string | null | number {
  /* ... */
}
</pre>
<p>You should define a type alias for the union or intersection duplicated in the code and replace all their occurrences with the alias name.</p>
<pre data-diff-id="1" data-diff-type="compliant">
type MyType = string | null | number;

function foo(x: MyType) {
  /* ... */
}

let bar: MyType = /* ... */;

function baz(): MyType {
  /* ... */
}
</pre>
<p>The rule disregards nullable types, irrespective of their frequency within the codebase. This includes types of the form <code>T | null |
undefined</code>, where <code>T</code> can represent any type.</p>
<pre>
function foo(x: T | null | undefined) {
  /* ... */
}
</pre>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
  <li> TypeScript Documentation - <a href="https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases">Type Aliases</a> </li>
  <li> TypeScript Documentation - <a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html">Unions and Intersection
  Types</a> </li>
  <li> Wikipedia - <a href="https://en.wikipedia.org/wiki/Rule_of_three_(computer_programming)">Rule of three (computer programming)</a> </li>
</ul>
